from army.core.instructions import *
from army.utils import endian

def _op(opcode_string):
    o = opcode_string
    return int(o[0]) * 2**3 + int(o[1]) * 2**2 + int(o[2]) * 2**1 + int(o[3])

class DataProcessingInstruction(Instruction):

    @classmethod
    def execute(cls,cpu,*args,**kwargs):
        Rd,Rn,sh = args
        S = kwargs['S']
        cpu.regs[Rd], carry = cls.result(Rn,sh)
        if S and carry is not None:
            CPSR = bits(cpu.regs[REG_CPSR])
            CPSR[29] = carry_out
            self.regs[REG_CPSR] = value(CPSR)

    @classmethod
    def result(cls,Rn,sh):
        raise NotImplementedError

class ANDInstruction:
    opcode = _op('0000')
    mnemonic = 'AND'
    name = 'Logical AND'

    @classmethod
    def result(cls,Rn,sh):
        return Rn & sh, None

class EORInstruction:
    opcode = _op('0001')
    mnemonic = 'EOR'
    name = 'Logical Exclusive OR'

    @classmethod
    def result(cls,Rn,sh):
        return Rn ~ sh, None

class SUBInstruction:
    opcode = _op('0010')
    mnemonic = 'SUB'
    name = 'Substract'

    @classmethod
    def result(cls,Rn,sh):
        Rd = Rn - sh
        N = endian.bit(Rd,31)
        if Rd == 0:
            Z = 1
        else:
            Z = 0
        #FIXME finish for other 2 bits of CPSR
        return Rn - sh, None

